package com.flow.framework.core.response;

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.flow.framework.common.exception.CheckedException;
import com.flow.framework.common.exception.UncheckedException;
import com.flow.framework.common.response.BaseResponse;
import com.flow.framework.core.constant.FrameworkCoreConstant;
import com.flow.framework.core.helper.response.ResponseHelper;
import com.flow.framework.core.holder.SecurityContextHolder;
import com.flow.framework.core.pojo.bo.InternationalBo;
import lombok.extern.slf4j.Slf4j;

import java.util.List;

/**
 * 信息返回统一封装
 *
 * @author luoguopiao
 * @version 0.0.1
 * @date 2022/2/5
 */
@Slf4j
public class Response<T> extends BaseResponse<T> {

    protected Response() {
    }

    /**
     * 是否成功
     *
     * @return 是否成功
     */
    @JsonIgnore
    public boolean isSuccess() {
        return FrameworkCoreConstant.SUCCESS_CODE.equals(code);
    }

    /**
     * 响应成功
     *
     * @param <T> T
     * @return 响应
     */
    public static <T> Response<T> success() {
        return success(null);
    }

    /**
     * 响应成功
     *
     * @param data 需要封装的数据
     * @param <T>  T
     * @return 响应
     */
    public static <T> Response<T> success(T data) {
        return build(0, data, null, null, null, null, null);
    }

    /**
     * 响应失败
     *
     * @param errorCode 错误码
     * @param <T>       T
     * @return 响应
     */
    public static <T> Response<T> failed(long errorCode) {
        log.error("response error, code: {}", errorCode);
        return build(errorCode, null, null, null, null, null, null);
    }

    /**
     * 响应失败
     *
     * @param errorCode 错误码
     * @param params    国际化参数
     * @param <T>       T
     * @return 响应
     */
    public static <T> Response<T> failed(long errorCode, List<String> params) {
        log.error("response error, code: {}", errorCode);
        return build(errorCode, null, params, null, null, null, null);
    }

    /**
     * 响应失败
     *
     * @param e   检查异常
     * @param <T> T
     * @return 响应
     */
    public static <T> Response<T> failed(CheckedException e) {
        long code = e.getCode();
        log.error("response error, code: {}, msg: {}, error: ", code, e.getMsg(), e);
        return build(code, null, e.getParams(), e.getSrcSystem(), e.getSrcCode(), e.getSrcMsg(), e.getSrcParams());
    }

    /**
     * 响应失败
     *
     * @param e   未检查异常
     * @param <T> T
     * @return 响应
     */
    public static <T> Response<T> failed(UncheckedException e) {
        long code = e.getCode();
        log.error("response error, code: {}, msg: {}, error: ", code, e.getMsg(), e);
        return build(code, null, e.getParams(), e.getSrcSystem(), e.getSrcCode(), e.getSrcMsg(), e.getSrcParams());
    }

    /**
     * 根据其他响应响应失败
     *
     * @param errorCode 错误码
     * @param response  其他响应
     * @param <T>       T
     * @return 响应
     */
    public static <T> Response<T> failed(long errorCode, Response<T> response) {
        log.error("response error, code: {}", errorCode);
        return build(errorCode, response.getData(), null, response.getSrcSystem(), response.getSrcCode(),
                response.getSrcMsg(), response.getSrcParams());
    }

    /**
     * 根据其他响应响应失败
     *
     * @param errorCode 错误码
     * @param params    国际化参数
     * @param response  其他响应
     * @param <T>       T
     * @return 响应
     */
    public static <T> Response<T> failed(long errorCode, List<String> params, Response<T> response) {
        log.error("response error, code: {}", errorCode);
        return build(errorCode, response.getData(), params, response.getSrcSystem(), response.getSrcCode(),
                response.getSrcMsg(), response.getSrcParams());
    }

    private static <T> Response<T> build(long code, T data, List<String> params, String srcSystem, String srcCode,
                                         String srcMsg, List<String> srcParams) {
        String codeString = String.valueOf(code);
        Response<T> response = new Response<>();
        if (0 == code) {
            response.setSystem(ResponseHelper.getCurrentSystemCode());
            response.setCode(codeString);
            response.setMsg("success");
        } else {
            if (SecurityContextHolder.isI18nRequired()) {
                InternationalBo internationalBo = ResponseHelper.i18nResponse(codeString, params);
                response.setSystem(internationalBo.getSystem());
                response.setCode(internationalBo.getCode());
                response.setMsg(internationalBo.getInternational());
            } else {
                response.setSystem(ResponseHelper.getCurrentSystemCode());
                response.setCode(codeString);
                response.setParams(params);
                response.setMsg("failed");
            }
        }
        response.setData(data);
        response.setSrcSystem(srcSystem);
        response.setSrcCode(srcCode);
        response.setSrcMsg(srcMsg);
        response.setSrcParams(srcParams);
        return response;
    }

    private void setSystem(String system) {
        super.system = system;
    }

    private void setCode(String code) {
        super.code = code;
    }

    private void setMsg(String msg) {
        super.msg = msg;
    }

    private void setData(T data) {
        super.data = data;
    }

    private void setParams(List<String> params) {
        super.params = params;
    }

    private void setSrcSystem(String srcSystem) {
        super.srcSystem = srcSystem;
    }

    private void setSrcCode(String srcCode) {
        super.srcCode = srcCode;
    }

    private void setSrcMsg(String srcMsg) {
        super.srcMsg = srcMsg;
    }

    private void setSrcParams(List<String> srcParams) {
        super.srcParams = srcParams;
    }
}
